Fail closed on unlabeled X posts and scrub upload provenance - #44
Open
0thernet wants to merge 5 commits into
Open
Fail closed on unlabeled X posts and scrub upload provenance#440thernet wants to merge 5 commits into
0thernet wants to merge 5 commits into
Conversation
Re-encode JPEG and PNG attachments to pixels-only bytes before X upload, reject residual C2PA/caBX markers, and treat a live Made with AI sparkle on CreateTweet or TweetResultByRestId as an unlabeled-copy failure. Do not delete the post. x-web still sends empty semantic_annotation_ids and rejects invented disclosure inputs. Co-authored-by: ben <0thernet@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The GIF provenance scan now rematerializes the file before INIT. A same-second rewrite can match inode identity and still fail the digest check. Both outcomes reject the upload before any media request. Co-authored-by: ben <0thernet@users.noreply.github.com>
The posts.publish implementation string now includes pixels-only scrub and fail-closed Made with AI readback, so the pinned contract hash moves with that reviewed description. Co-authored-by: ben <0thernet@users.noreply.github.com>
Current x-web and official x closures now include pixels-only image re-encoding and Made with AI label detection, so the durable contract inventory hashes move with those sources. Co-authored-by: ben <0thernet@users.noreply.github.com>
After live I/O, an optional admission file that changes while it is read is the same fail-closed outcome as an auth-realm mismatch. Remap that helper error so Linux cannot publish the discarded result under a lower-level open failure. Co-authored-by: ben <0thernet@users.noreply.github.com>
0thernet
marked this pull request as ready for review
August 24, 2026 00:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closed PRs #24 and #26 documented the unlabeled-copy rule but did not land. #39 later shipped skill guidance, empty
semantic_annotation_ids, and rejection of invented CreateTweet AI fields. That is still not enough: X can auto-apply Made with AI from C2PA or other provenance in uploaded bytes even when Content disclosure is OFF. The composer post https://x.com/hraness/status/2091626299513041128 shows the live failure — disclosure OFF before Post, then a locked/greyed toggle after X auto-labeled.This PR adds a durable publish-path fix. It does not reopen #24 or #26.
Media scrub before upload
JPEG and PNG attachments are re-encoded to pixels-only bytes before INIT/APPEND (x-web) or the official one-shot upload. Ancillary provenance is dropped:
caBX/C2PA, XMP/iTXt, Exif, IPTC, and Adobe APP/COM markers. If the bytes that would be uploaded still match/c2pa|caBX|trainedAlgorithmic|digitalSourceType/i, the run fails before dispatch. x-webposts.publishremains PNG-or-MP4; officialxstill accepts JPEG/PNG for one-shot images. GIFs are scanned, not re-encoded.Fail-closed Made with AI readback
After CreateTweet (and the independent TweetResultByRestId read used by the live web UI), a Made with AI / AI-generated / sparkle annotation is a terminal unlabeled-copy failure. The exact error is:
X applied Made with AI label; publish failed for unlabeled-copy policyThe post may already exist. Wrench does not delete it. The run journal forbids
failedafter dispatch starts, so x-web reportsindeterminatewith that error and keeps the ledger.x-webrejectsmade_with_ai,content_disclosure,ai_generated_disclosure, andsemantic_annotation_idsbefore bootstrap. CreateTweet still sends emptysemantic_annotation_idsand no invented disclosure field.Official
xstill omitsmade_with_aiunless the caller explicitly setstruefor authorized AI media, and it rejects a labeled create response when that flag is not true.Skill
skills/wrench/references/x-ai-disclosure.mdnow documents: prefer Wrench; scrub media; never setmade_with_aifor user-supplied copy; composer only as a last resort with disclosure OFF; live permalink check; locked toggle = auto-label = failed publish; do not delete unless the user asks. Package smoke and the skill test fail if a packaged skill drops the unlabeled rule.R3 preview/confirm is unchanged except for this new terminal failure mode.
Linux Required flake
The first Linux
checkrun failed only inpersistent read client > discards live output when an admission holder replaces auth a-to-b. A concurrent admission rewrite can throwcould not safely open optional read projection admission(state file changed while it was read) before the auth-realm check. After live I/O that is now remapped to the same discard error so the live result cannot be published. macOScheckwas already green.